package com.learning.platform.service;

import com.learning.platform.dto.CourseRequest;
import com.learning.platform.dto.CourseResponse;
import com.learning.platform.dto.CourseSearchRequest;
import com.learning.platform.entity.Course;
import com.learning.platform.enums.CourseStatus;
import com.learning.platform.enums.ErrorCode;
import com.learning.platform.exception.BusinessException;
import com.learning.platform.entity.Lesson;
import com.learning.platform.repository.*;

import java.util.List;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.Pageable;
import org.springframework.data.domain.PageRequest;
import org.springframework.data.domain.Sort;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

/**
 * 课程服务类
 * 处理课程的CRUD操作、搜索、发布等业务逻辑
 */
@Service
@Transactional
public class CourseService {
    
    private final CourseRepository courseRepository;
    private final LessonRepository lessonRepository;
    private final EnrollmentRepository enrollmentRepository;
    private final ProgressRepository progressRepository;
    private final CourseReviewRepository reviewRepository;
    private final UserFavoriteRepository favoriteRepository;
    
    /**
     * 构造函数，注入数据访问接口
     */
    public CourseService(CourseRepository courseRepository, 
                        LessonRepository lessonRepository,
                        EnrollmentRepository enrollmentRepository,
                        ProgressRepository progressRepository,
                        CourseReviewRepository reviewRepository,
                        UserFavoriteRepository favoriteRepository) {
        this.courseRepository = courseRepository;
        this.lessonRepository = lessonRepository;
        this.enrollmentRepository = enrollmentRepository;
        this.progressRepository = progressRepository;
        this.reviewRepository = reviewRepository;
        this.favoriteRepository = favoriteRepository;
    }
    
    /**
     * 获取已发布的课程列表
     * @param keyword 搜索关键词
     * @param pageable 分页参数
     * @return 课程列表分页数据
     */
    @Transactional(readOnly = true)
    public Page<CourseResponse> getPublishedCourses(String keyword, Pageable pageable) {
        return courseRepository.findPublishedCourses(CourseStatus.PUBLISHED, keyword, pageable)
                .map(CourseResponse::new);
    }
    
    /**
     * 使用高级搜索获取课程列表
     * @param searchRequest 搜索请求参数，包含分类、关键词、难度、价格范围等筛选条件
     * @return 符合条件的课程列表分页数据
     */
    @Transactional(readOnly = true)
    public Page<CourseResponse> searchCourses(CourseSearchRequest searchRequest) {
        // 构建分页和排序
        Sort sort = buildSort(searchRequest.getSortBy());
        Pageable pageable = PageRequest.of(
            searchRequest.getPage() - 1, 
            searchRequest.getPageSize(), 
            sort
        );
        
        // 调用Repository的高级查询方法
        return courseRepository.findCoursesWithFilters(
            searchRequest.getCategoryId(),
            searchRequest.getKeyword(),
            searchRequest.getDifficulty(),
            searchRequest.getMinPrice(),
            searchRequest.getMaxPrice(),
            searchRequest.getSortBy(),
            pageable
        ).map(CourseResponse::new);
    }
    
    /**
     * 构建排序条件
     * @param sortBy 排序字段
     * @return 排序对象
     */
    private Sort buildSort(String sortBy) {
        if (sortBy == null) {
            return Sort.by(Sort.Direction.DESC, "createdAt");
        }
        
        return switch (sortBy) {
            case "price" -> Sort.by(Sort.Direction.ASC, "price");
            case "rating" -> Sort.by(Sort.Direction.DESC, "averageRating");
            case "popular" -> Sort.by(Sort.Direction.DESC, "enrollmentCount");
            case "latest" -> Sort.by(Sort.Direction.DESC, "createdAt");
            default -> Sort.by(Sort.Direction.DESC, "createdAt");
        };
    }
    
    /**
     * 根据ID获取课程详情
     * @param id 课程ID
     * @return 课程详情响应
     * @throws BusinessException 当课程不存在时抛出
     */
    @Transactional(readOnly = true)
    public CourseResponse getCourseById(Long id) {
        Course course = courseRepository.findById(id)
                .orElseThrow(() -> new BusinessException(ErrorCode.COURSE_NOT_FOUND));
        
        // 使用安全的构造函数创建CourseResponse，避免懒加载异常
        CourseResponse response = new CourseResponse(course);
        
        // 通过数据库查询获取课时数量，避免懒加载
        long lessonCount = lessonRepository.countByCourseId(id);
        response.setLessonCount((int) lessonCount);
        
        return response;
    }
    
    /**
     * 获取指定教师创建的课程列表
     * @param teacherId 教师ID
     * @param pageable 分页参数
     * @return 教师课程列表分页数据
     */
    @Transactional(readOnly = true)
    public Page<CourseResponse> getTeacherCourses(Long teacherId, Pageable pageable) {
        return courseRepository.findByTeacherIdOrderByCreatedAtDesc(teacherId, pageable)
                .map(CourseResponse::new);
    }
    
    /**
     * 创建新课程
     * @param request 课程创建请求参数
     * @param teacherId 创建课程的教师ID
     * @return 创建后的课程详情响应
     */
    public CourseResponse createCourse(CourseRequest request, Long teacherId) {
        Course course = new Course(request.getTitle(), request.getDescription(), teacherId);
        course.setCoverUrl(request.getCoverUrl());
        course.setCategoryId(request.getCategoryId());
        course.setPrice(request.getPrice());
        course.setDifficulty(request.getDifficulty());
        course = courseRepository.save(course);
        return new CourseResponse(course);
    }
    
    /**
     * 更新课程信息
     * @param id 要更新的课程ID
     * @param request 课程更新请求参数
     * @param teacherId 当前操作的教师ID
     * @return 更新后的课程详情响应
     * @throws BusinessException 当课程不存在或教师没有权限时抛出
     */
    public CourseResponse updateCourse(Long id, CourseRequest request, Long teacherId) {
        Course course = courseRepository.findById(id)
                .orElseThrow(() -> new BusinessException(ErrorCode.COURSE_NOT_FOUND));
        
        if (!course.getTeacherId().equals(teacherId)) {
            throw new BusinessException(ErrorCode.PERMISSION_DENIED);
        }
        
        course.setTitle(request.getTitle());
        course.setDescription(request.getDescription());
        course.setCoverUrl(request.getCoverUrl());
        course.setCategoryId(request.getCategoryId());
        course.setPrice(request.getPrice());
        course.setDifficulty(request.getDifficulty());
        
        return new CourseResponse(courseRepository.save(course));
    }
    
    /**
     * 下线课程
     * @param id 要下线的课程ID
     * @param teacherId 当前操作的教师ID
     * @throws BusinessException 当课程不存在或教师没有权限时抛出
     */
    public void unpublishCourse(Long id, Long teacherId) {
        Course course = courseRepository.findById(id)
                .orElseThrow(() -> new BusinessException(ErrorCode.COURSE_NOT_FOUND));
        
        if (!course.getTeacherId().equals(teacherId)) {
            throw new BusinessException(ErrorCode.PERMISSION_DENIED);
        }
        
        course.setStatus(CourseStatus.DRAFT);
        courseRepository.save(course);
    }

    /**
     * 删除课程
     * @param id 要删除的课程ID
     * @param teacherId 当前操作的教师ID
     * @throws BusinessException 当课程不存在或教师没有权限时抛出
     */
    @Transactional
    public void deleteCourse(Long id, Long teacherId) {
        Course course = courseRepository.findById(id)
                .orElseThrow(() -> new BusinessException(ErrorCode.COURSE_NOT_FOUND));
        
        if (!course.getTeacherId().equals(teacherId)) {
            throw new BusinessException(ErrorCode.PERMISSION_DENIED);
        }
        
        // 删除关联数据（按依赖顺序）
        deleteCourseRelatedData(id);
        
        // 最后删除课程本身
        courseRepository.delete(course);
    }
    
    /**
     * 删除课程的所有关联数据
     * @param courseId 课程ID
     */
    private void deleteCourseRelatedData(Long courseId) {
        try {
            // 1. 先获取课程的所有章节ID
            List<Lesson> lessons = lessonRepository.findByCourseIdOrderByOrderNoAsc(courseId);
            List<Long> lessonIds = lessons.stream().map(Lesson::getId).collect(java.util.stream.Collectors.toList());
            
            // 2. 删除学习进度记录（基于章节ID）
            if (!lessonIds.isEmpty()) {
                progressRepository.deleteByLessonIdIn(lessonIds);
            }
            
            // 3. 删除选课记录
            enrollmentRepository.deleteByCourseId(courseId);
            
            // 4. 删除课程评价
            reviewRepository.deleteByCourseId(courseId);
            
            // 5. 删除收藏记录
            favoriteRepository.deleteByCourseId(courseId);
            
            // 6. 最后删除课程章节
            lessonRepository.deleteByCourseId(courseId);
            
            // 注意：question_bank, exams, certificates 已经设置了 CASCADE DELETE，会自动删除
            
        } catch (Exception e) {
            throw new BusinessException("删除课程关联数据失败: " + e.getMessage());
        }
    }
    
    /**
     * 发布课程
     * @param id 要发布的课程ID
     * @param teacherId 当前操作的教师ID
     * @return 发布后的课程详情响应
     * @throws BusinessException 当课程不存在或教师没有权限时抛出
     */
    public CourseResponse publishCourse(Long id, Long teacherId) {
        Course course = courseRepository.findById(id)
                .orElseThrow(() -> new BusinessException(ErrorCode.COURSE_NOT_FOUND));
        
        if (!course.getTeacherId().equals(teacherId)) {
            throw new BusinessException(ErrorCode.PERMISSION_DENIED);
        }
        
        // 验证课程是否具备发布条件
        validateCourseForPublish(course);
        
        course.setStatus(CourseStatus.PUBLISHED);
        return new CourseResponse(courseRepository.save(course));
    }
    
    /**
     * 验证课程是否具备发布条件
     * @param course 要验证的课程
     * @throws BusinessException 当课程不满足发布条件时抛出
     */
    private void validateCourseForPublish(Course course) {
        // 检查课程基本信息
        if (course.getTitle() == null || course.getTitle().trim().isEmpty()) {
            throw new BusinessException("课程标题不能为空");
        }
        
        if (course.getDescription() == null || course.getDescription().trim().isEmpty()) {
            throw new BusinessException("课程描述不能为空");
        }
        
        // 检查课程是否有章节
        long lessonCount = lessonRepository.countByCourseId(course.getId());
        if (lessonCount == 0) {
            throw new BusinessException("课程至少需要包含一个章节才能发布");
        }
        
        // 检查课程状态
        if (course.getStatus() == CourseStatus.PUBLISHED) {
            throw new BusinessException("课程已经发布，无需重复发布");
        }
    }
}

